package cn.hinglo.common.utils;

import cn.hutool.core.codec.Base64;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;


/**
 * @createTime: 2018/9/19 10:38
 * @author: HingLo
 * @description: token 校验与创建工具
 */
@Slf4j
public class JwtUtil {

    /**
     * 定义key
     */
    private final static String stringKey = "63A9F0EA7BB98050796B649E85481845";

    /**
     * 定义有效时间 设置有效时间为30 分钟,如果设置小于0,则表示该token不过期
     */
    private final static int ttlMillis = 1000 * 60 * 30;

    /**
     * 由字符串生成加密key
     *
     * @return 加密key
     */
    private static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(stringKey);
        return new SecretKeySpec(encodedKey, "AES");
    }

    /**
     * 创建jwt
     *
     * @param id      id
     * @param subject 加密主题的内容
     * @return token字符串
     */
    public static String createJWT(String id, String subject) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey key = generalKey();
        JwtBuilder builder = Jwts.builder().setId(id).setIssuedAt(now).setSubject(subject).signWith(signatureAlgorithm, key);
        if (ttlMillis > 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    /**
     * 解密jwt
     *
     * @param token 解密的token
     * @return Claims 对象
     */
    public static Claims parseJWT(String token) {
        SecretKey key = generalKey();
        return Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
    }

    /**
     * 解密jwt 中的Id
     *
     * @param token token
     * @return Id
     * @throws Exception 时间过期或者解密失败抛出的异常
     */
    public static String parseIdJWT(String token) {
        try {
            return parseJWT(token).getId();
        } catch (Exception e) {
            // 日志记录
            log.info("解密失败,错误信息如下---->{}", e.getMessage());
            // 如果解密失败，就直接返回一个null
            return null;
        }
    }

}
